package com.tom.AIAnswer.scoring;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tom.AIAnswer.manager.AiManager;
import com.tom.AIAnswer.model.dto.question.QuestionContentDTO;
import com.tom.AIAnswer.model.dto.userAnswer.QuestionAnswerDTO;
import com.tom.AIAnswer.model.entity.App;
import com.tom.AIAnswer.model.entity.Question;
import com.tom.AIAnswer.model.entity.ScoringResult;
import com.tom.AIAnswer.model.entity.UserAnswer;
import com.tom.AIAnswer.model.vo.QuestionVO;
import com.tom.AIAnswer.service.AppService;
import com.tom.AIAnswer.service.QuestionService;
import com.tom.AIAnswer.service.ScoringResultService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * AI测评类评分策略
 * 计算各题答案更倾向于哪种人格类型
 */
@ScoringStrategyConfig(appType = 1, scoringStrategy = 1)
public class AITestScoringStrategy implements ScoringStrategy {

    @Resource
    private QuestionService questionService;

    @Resource
    private AiManager aiManager;

    private static final String AI_TEST_SCORING_SYSTEM_MESSAGE = "你是一位严谨的判题专家，我会给你如下信息：\n" +
            "```\n" +
            "应用名称，\n" +
            "【【【应用描述】】】，\n" +
            "题目和用户回答的列表：格式为 [{\"title\": \"题目\",\"answer\": \"用户回答\"}]\n" +
            "```\n" +
            "\n" +
            "请你根据上述信息，按照以下步骤来对用户进行评价：\n" +
            "1. 要求：需要给出一个明确的评价结果，包括评价名称（尽量简短）和评价描述（尽量详细，大于 200 字）\n" +
            "2. 严格按照下面的 json 格式输出评价名称和评价描述\n" +
            "```\n" +
            "{\"resultName\": \"评价名称\", \"resultDesc\": \"评价描述\"}\n" +
            "```\n" +
            "3. 返回格式必须为 JSON 对象";


    /**
     * AI根据各题答案评测更倾向于哪种人格类型
     * 如下示例：
     * {
     *   "resultName": "内向思考型（INTJ）",
     *   "resultDesc": "根据你的回答，你的MBTI性格类型为内向思考型（INTJ）。这是一个非常独立和有逻辑思维的性格类型。你更喜欢独自工作，思考问题时深入且系统化。在安排活动时，你倾向于有计划和方法，这表明你对结构和组织有一定的偏好。你对规则持有自己的看法，既不盲从也不完全反抗，显示出你有一定的独立判断能力。在社交场合中，你虽然不太主动，但能保持礼貌和适宜的表现。面对新挑战时，你通常愿意接受，并且喜欢事先准备好。在做决定时，你既理性又考虑周到，不会轻易受情绪影响。你的日常安排井井有条，显示出你重视效率和计划性。遇到问题时，你倾向于独立解决，而不是寻求他人帮助。你对时间的看法也反映出你对效率和及时的重视。总体来说，INTJ类型的人通常有远见，喜欢深入思考，适合从事需要分析和策略的工作。"
     * }
     * @param choices
     * @param app
     * @return
     */
    @Override
    public UserAnswer doScoring(List<String> choices, App app) {
      //1. 根据应用id查询对应题目
        Long appId = app.getId();
        Question question = questionService.getOne(Wrappers.lambdaQuery(Question.class).eq(Question::getAppId, appId));
        //2. 根据题目的id查询题目内容
        QuestionVO questionVO = QuestionVO.objToVo(question);
        List<QuestionContentDTO> questionContentDTOList = questionVO.getQuestionContent();


        //AI接受两个信息，一个系统信息（系统信息是一个固定的字符串），一个用户信息（用户信息是拼接成的）
        //2. 获取用户信息
        String userMessage = getAiTestScoringUserMessage(app, questionContentDTOList, choices);
        //3. 调用AI测评接口，获取AI测评结果
        String AiTestResult = aiManager.sendSyncStableAIRequest(AI_TEST_SCORING_SYSTEM_MESSAGE, userMessage);

        //4. 根据AI测评结果，截取AI回复的信息内容
        int start = AiTestResult.indexOf("{");
        int end = AiTestResult.lastIndexOf("}");
        String json = AiTestResult.substring(start, end + 1);
        System.out.println(json);

        //把json转换成UserAnswer对象类型，不过只有当前对象的resultName和resultDesc是有填充值的
        UserAnswer userAnswer = JSONUtil.toBean(json, UserAnswer.class);

        //4. 根据AI评测结果，更新用户对应属性
        userAnswer.setAppId(appId);
        userAnswer.setAppType(app.getAppType());
        userAnswer.setScoringStrategy(app.getScoringStrategy());
        userAnswer.setChoices(JSONUtil.toJsonStr(choices));
        return userAnswer;
    }


    /**
     * 拼接用户信息（应用名称+题目标题+用户选择的答案）
     * 如这种类型：
     * {
     *   "appName": "MBTI 性格测试",
     *   "appDesc": "测试你的 MBTI 性格",
     *   "question": [
     *     {
     *       "title": "你喜欢和人交流",
     *       "answer": "喜欢"
     *     }
     *               ]
     * }
     * @param app
     * @param questionContentDTOList
     * @param choices
     * @return
     */
    private String getAiTestScoringUserMessage(App app, List<QuestionContentDTO> questionContentDTOList, List<String> choices) {
        StringBuilder userMessage = new StringBuilder();
        //从app对象获取应用名和应用描述
        userMessage.append(app.getAppName()).append("\n");
        userMessage.append(app.getAppDesc()).append("\n");
        //获取题目信息列表中每一题的标题和此题用户选择的答案，并封装到一个新的列表中
        List<QuestionAnswerDTO> questionAnswerDTOList = new ArrayList<>();
        for (int i = 0; i < questionContentDTOList.size(); i++) {
            QuestionAnswerDTO questionAnswerDTO = new QuestionAnswerDTO();
            questionAnswerDTO.setTitle(questionContentDTOList.get(i).getTitle());
            questionAnswerDTO.setUserAnswer(choices.get(i));
            questionAnswerDTOList.add(questionAnswerDTO);
        }
        userMessage.append(JSONUtil.toJsonStr(questionAnswerDTOList));
        return userMessage.toString();
    }
}
